﻿/*
 * 由SharpDevelop创建。
 * 用户： lucifer
 * 日期: 2011/3/18
 * 时间: 9:55
 * 
 * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
 */
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Yidu.Persister.Mapping {
    /// <summary>
    /// Description of TableMappingHelper.
    /// </summary>
    public class TableMappingHelper {
        private TableMappingHelper() {

        }

        private static TableMappingHelper mappingHelper = new TableMappingHelper();
        private Dictionary<string, TableMappingInfo> tableNameDict = new Dictionary<string, TableMappingInfo>();
        private Dictionary<string, TableMappingInfo> entryNameDict = new Dictionary<string, TableMappingInfo>();
        private IDbNameGuesser guesser = new DbNameGuesser();

        public static TableMappingHelper Instance {
            get {
                return mappingHelper;
            }
        }

        public TableMappingInfo GetTableMapping(string tableName) {
            return tableNameDict[tableName];
        }

        public void RemoveTableMapping(string  tableName)
        {
            TableMappingInfo info = GetTableMapping(tableName);
            tableNameDict.Remove(info.TableName);
            entryNameDict.Remove(info.EntryName);
            info = null;
        }

        public TableMappingInfo GetEntryMapping(Type entryType) {
            if (entryType == null) {
                return null;
            }
            string entryName = entryType.Name;
            if (entryNameDict.ContainsKey(entryName)) {
                return entryNameDict[entryName];
            }
            List<string> tableNameList = guesser.getPossibleTableNames(entryName);
            if (tableNameList.Count == 0) {
                throw new Exception(string.Format("找不到实体对应的数据库表名称！实体名称 = {0}", entryName));
            } else if (tableNameList.Count > 1) {
                throw new Exception(string.Format("找到多个实体对应的数据库表名称！表个数 = {0}，例如： {0},{1},......", tableNameList.Count, tableNameList[0], tableNameList[1]));
            }

            TableMappingInfo tableMapping = new TableMappingInfo();
            tableMapping.EntryName = entryName;
            tableMapping.EntryType = entryType;
            tableMapping.TableName = tableNameList[0];


            IDao dao = DaoFactory.Instance.Dao;
            List<Dictionary<string, object>> primaryKeyList = dao.List(TablePrimaryKeySql, false,"tableName",tableMapping.TableName);

            foreach (var dict in primaryKeyList) {
                tableMapping.PrimaryKeys.Add(Convert.ToString(dict["primary_key_name"]));
            }
    
           
            List<Dictionary<string, object>> fieldNameList = guesser.getTableFields(tableMapping.TableName);
            PropertyInfo[] props = entryType.GetProperties();
            foreach (PropertyInfo p in props) {
                List<string> columnNameList = guesser.getPossibleColumnNames(p.Name, fieldNameList);
                if (columnNameList.Count == 1) {
                    FieldMappingInfo fieldMapping = new FieldMappingInfo();
                    fieldMapping.PropertyType = p.PropertyType;
                    fieldMapping.PropertyName = p.Name;
                    fieldMapping.PropertyInfo = p;
                    fieldMapping.FieldName = columnNameList[0];

                    foreach (Dictionary<string, object> dict in fieldNameList) {
                        if (fieldMapping.FieldName.Equals(dict["real_name"])) {
                            fieldMapping.FieldType = Convert.ToString(dict["type_name"]);
                            fieldMapping.FieldLength = Convert.ToInt32(dict["length"]);
                        }
                    }

                    tableMapping.FieldMapping[fieldMapping.FieldName] = fieldMapping;
                    tableMapping.PropertyMapping[fieldMapping.PropertyName] = fieldMapping;

                } else if (columnNameList.Count > 1) {
                    throw new Exception(string.Format("找到属性对应多个表字段名称！字段个数 = {0}，例如： {1} {2}", columnNameList.Count, columnNameList[0], columnNameList[1]));
                }
            }
            return tableMapping;


        }



        #region SQL语句

        private const string TablePrimaryKeySql = @"SELECT syscolumns.name primary_key_name
                                                            FROM   syscolumns,
                                                                   sysobjects,
                                                                   sysindexes,
                                                                   sysindexkeys
                                                            WHERE  syscolumns.id = OBJECT_ID(@tableName)
                                                                   AND sysobjects.xtype = 'PK'
                                                                   AND sysobjects.parent_obj = syscolumns.id
                                                                   AND sysindexes.id = syscolumns.id
                                                                   AND sysobjects.name = sysindexes.name
                                                                   AND sysindexkeys.id = syscolumns.id
                                                                   AND sysindexkeys.indid = sysindexes.indid
                                                                   AND syscolumns.colid = sysindexkeys.colid";
        #endregion
    }
}
